package com.kuang.auth;

import com.kuang.common.err.ValidationException;
import com.kuang.entity.User;
import com.kuang.local.UserThreadLocal;
import com.kuang.service.JwtService;
import com.kuang.service.UserService;
import com.kuang.vo.AuthResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author 飞哥
 * @Title: 学相伴出品
 * @Description: 我们有一个学习网站：https://www.kuangstudy.com
 * @date 2021/9/6 14:42
 */
@Aspect
@Component
@Slf4j
public class LoginCheckAspect implements Ordered {

    @Autowired
    private JwtService jwtService;
    @Autowired
    private UserService userService;
    @Autowired
    private ApplicationContext applicationContext;

    private static final String AUTH = "Authorization";
    private static final String AUTH_USERNAME = "ksd-user-name";

    // 定义aop的切入点
    @Pointcut("@annotation(com.kuang.auth.CheckLogin)")
    public void checkloginponit() {
        log.info("cut");
    }

    @Pointcut("@annotation(com.kuang.auth.CheckAdminLogin)")
    public void checkadminloginponit() {
        log.info("cut");
    }

    @Before("checkloginponit()")
    public void checkLogin(JoinPoint joinPoint) {
        this.checkLogin();
    }

    @Before("checkadminloginponit()")
    public void checkAdminLogin(JoinPoint joinPoint) {
        this.checkLogin();
        // 2: 获取方法上的签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        CheckAdminLogin checkAdminLogin = method.getAnnotation(CheckAdminLogin.class);
        String value = checkAdminLogin.value();
        log.info("2---权限必须是：{}",value);
        if (StringUtils.isEmpty(value)) {
            throw new ValidationException(300, "请输入角色!!");
        }

        User user = UserThreadLocal.get();
        log.info("3----------------权限必须是：{},{}",value,user.getRole());
        if (!user.getRole().equals(value)) {
            throw new ValidationException(300, "用户权限不够!");
        }
    }


    @After("checkloginponit()")
    public void methodend1() {
        UserThreadLocal.remove();
        log.info("1---方法执行结束...............");
    }

    @After("checkadminloginponit()")
    public void methodend2() {
        UserThreadLocal.remove();
        log.info("2---方法执行结束...............");
    }

    private void checkLogin() {
        log.info("拦截进来了....................");
        // 1：获取服务请求的对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        HttpServletResponse response = requestAttributes.getResponse();
        // 2: 从请求头中获取token
        String openid = getParam(request, AUTH_USERNAME);
        String token = getParam(request, AUTH);

        if (StringUtils.isEmpty(token)) {
            throw new ValidationException(300, "Authorization不允许为空，请重新登录!!!");
        }

        if (StringUtils.isEmpty(openid)) {
            throw new ValidationException(300, "openid不允许为空，请重新登录!!!");
        }
        // 开始对你token和你用户名进行token校验，如果正常直接返回，如果不正常抛出异常
        AuthResponse authResponse = jwtService.verifyOpenid(token, openid);
        // 如果不等于1，说明token和用户名校验失败
        if (authResponse.getCode() != 1L) {
            log.error("token invalid error");
            throw new ValidationException(300, "token valid fail!!!");
        }

        User user = userService.getUserByOpenid(openid);
        if (user == null) {
            log.error("user invalid error");
            throw new ValidationException(300, "user valid fail!!!");
        }

        UserThreadLocal.put(user);
    }

    public static String getParam(HttpServletRequest request, String filedName) {
        //1 :在参数里面区获取对应filedName的值
        String param = request.getParameter(filedName);
        // 2:如果不存在
        if (StringUtils.isEmpty(param)) {
            // 3: 就请求头区获取对应filedName的值
            param = request.getHeader(filedName);
        }
        return param;
    }

    @Override
    public int getOrder() {
        return 999999;
    }
}
